package impl

import (
	"context"
	"vblog/app/token"
	"vblog/app/user"
	"vblog/conf"
	"vblog/exception"
	"vblog/ioc"

	"gorm.io/gorm"
)

var _ token.Service = &TokenServiceImpl{}

type TokenServiceImpl struct {
	// 依赖user模块
	user user.Service
	db   *gorm.DB
}

// 注册到ioc
func init() {
	ioc.Controller().RegistryIoc(&TokenServiceImpl{})
}

// 初始化
func (u *TokenServiceImpl) Init() {
	u.user = ioc.Controller().Get("user").(user.Service)
	u.db = conf.C().Mysql.GetConn()

}

// 实现Name
func (u *TokenServiceImpl) Name() string {
	return "token"
}

// func NewTokenServiceImpl(userSvcImpl user.Service) *TokenServiceImpl {
// 	return &TokenServiceImpl{
// 		user: userSvcImpl,
// 		db:   conf.C().Mysql.GetConn(),
// 	}
// }

func (t *TokenServiceImpl) Login(ctx context.Context, req *token.LoginRequest) (*token.Token, error) {
	// 查询并验证用户
	describe_req := user.NewDescribeUserRequest_By_Username(req.Username)
	u, err := t.user.DescribeUser(ctx, describe_req)
	if err != nil {
		if exception.IsNotFound(err) {
			return nil, exception.NewAuthFailed("用户名或密码不正确")
		}
		return nil, err
	}
	if err = u.CheckPassword(req.Password); err != nil {
		return nil, exception.NewAuthFailed("用户名或密码不正确")
	}

	// 颁发token
	tk := token.NewToken()
	tk.UserId = u.Id
	tk.UserName = u.Username

	// 保存token
	if err := t.db.WithContext(ctx).Create(tk).Error; err != nil {
		return nil, err
	}

	// 返回token

	return tk, nil
}

func (t *TokenServiceImpl) ValiateToken(ctx context.Context, req *token.ValiateToken) (*token.Token, error) {
	// 验证token是否存在
	tk := token.NewToken()
	err := t.db.WithContext(ctx).Where("access_token = ?", req.AccessToken).First(tk).Error
	if err != nil {
		return nil, err
	}

	// 是否过期
	if err = tk.IsExpired(); err != nil {
		return nil, err
	}

	// 返回token
	return tk, nil
}

func (t *TokenServiceImpl) Logout(ctx context.Context, req *token.LogoutRequest) error {
	// 查找token
	tk := token.NewToken()
	err := t.db.WithContext(ctx).Where("access_token = ?", req.AccessToken).First(tk).Error
	if err != nil {
		return err
	}

	// 销毁token
	err = t.db.WithContext(ctx).Where("access_token = ?", req.AccessToken).Delete(tk).Error
	if err != nil {
		return err
	}

	return nil
}
